package com.kuangstudy.service.random;

import com.alibaba.fastjson.JSON;
import com.kuangstudy.constant.RedisConstants;
import com.kuangstudy.entity.Product;
import com.kuangstudy.mapper.ProductMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * @author renyitong
 * @version 1.0.0
 * @createTime 2023年09月19日
 * @Description 采用Redis完成数据信息的随机展示
 * 在网站中，随机数据的展示一般都会放置在主页这个时候展示的区域是有限的，通常并发量非常大。
 * 如果采用数据库来实现肯定是扛不住这么大的高并发。所以采用redis来实现是一个而非常明智的选择。
 * 1：先把需要随机展示的商品，加载到redis的内存数据结构中。
 * 2：通过srandmember命令随机获取一批数据出来即可。
 */
@Service
@Slf4j
public class DataRandomService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductMapper productMapper;

    @PostConstruct
    private void initData() {
        // 防止key的重复加载
        if (!redisTemplate.hasKey(RedisConstants.DB_PRODUCT_LIST_SET)) {
            List<Product> productList = productMapper.selectAll();
            if (!productList.isEmpty()) {
                productList.forEach(product ->
                        this.redisTemplate.opsForSet().add(RedisConstants.DB_PRODUCT_LIST_SET,
                                JSON.toJSONString(product)));
            }

            // 设置过期时间，防止redis的内存紧张
            redisTemplate.expire(RedisConstants.DB_PRODUCT_LIST_SET, 30, TimeUnit.DAYS);
        }
    }

    /**
     * 获取随机的商品数据
     *
     * @return
     */
    public List<Product> getRandomProductInfo() {
        // 如果redis中过期了
        if (!this.redisTemplate.hasKey(RedisConstants.DB_PRODUCT_LIST_SET)) {
            // 查询数据库中所有的产品信息
            List<Product> productList = productMapper.selectAll();
            if (!productList.isEmpty()) {
                // 放入到redis的set数据结构
                productList.forEach(product ->
                        this.redisTemplate.opsForSet().add(RedisConstants.DB_PRODUCT_LIST_SET,
                                JSON.toJSONString(product)));
            }
            // java代码随机生成10条产品数据返回出去
            Random rand = new Random();
            List<Product> randomList = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                int randomIndex = rand.nextInt(productList.size());
                randomList.add(productList.get(randomIndex));
            }
        }

        // 相当于执行命令：srandmember db:product:list:set 10
        List<String> productStrList = this.redisTemplate.opsForSet().randomMembers(RedisConstants.DB_PRODUCT_LIST_SET, 10L);
        List<Product> productList = productStrList.stream().map(s -> JSON.parseObject(s, Product.class)).collect(Collectors.toList());
        return productList;
    }



}
